package assistant

/*
Copyright 2021-2025 The k8gb Contributors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Generated by GoLic, for more details see: https://github.com/AbsaOSS/golic
*/

import (
	"context"
	"fmt"

	"github.com/k8gb-io/k8gb/controllers/resolver"

	"github.com/k8gb-io/k8gb/controllers/logging"

	corev1 "k8s.io/api/core/v1"
	"sigs.k8s.io/controller-runtime/pkg/client"
)

const CoreDNSServiceLabelName = "app.kubernetes.io/name"
const CoreDNSServiceLabelValue = "coredns"

var coreDNSServiceLabel = fmt.Sprintf("%s=%s", CoreDNSServiceLabelName, CoreDNSServiceLabelValue)

// CoreDNSService is common wrapper operating on GSLB instance.
// It uses apimachinery client to call kubernetes API
type CoreDNSService struct {
	client  client.Client
	config  resolver.Config
	context context.Context
}

var log = logging.Logger()

func NewCoreDNSServiceAssistant(context context.Context, client client.Client, config resolver.Config) *CoreDNSService {
	return &CoreDNSService{
		client:  client,
		config:  config,
		context: context,
	}
}

// GetResource returns the CoreDNS Service
func (r *CoreDNSService) GetResource() (*corev1.Service, error) {
	serviceList, err := getObjectList(r.context, r.client, &corev1.ServiceList{}, coreDNSServiceLabel, r.config.K8gbNamespace)
	if err != nil {
		return nil, err
	}
	if len(serviceList.Items) == 0 {
		return nil, fmt.Errorf("no coreDNS service was found. Check if CoreDNS is exposed correctly")
	}
	coreDNSService := &serviceList.Items[0]
	return coreDNSService, nil
}

// GetExposedIPs retrieves list of IP's exposed by CoreDNS
func (r *CoreDNSService) GetExposedIPs() ([]string, *corev1.Service, error) {
	coreDNSService, err := r.GetResource()
	if err != nil {
		return nil, nil, err
	}
	if coreDNSService.Spec.Type == "ClusterIP" {
		if len(coreDNSService.Spec.ClusterIPs) == 0 {
			return nil, nil, fmt.Errorf("no ClusterIPs found in service %s", coreDNSService.Name)
		}
		return coreDNSService.Spec.ClusterIPs, nil, nil
	}
	if len(coreDNSService.Status.LoadBalancer.Ingress) == 0 {
		return nil, nil, fmt.Errorf("no LoadBalancer ExternalIPs are found")
	}
	var ipList []string
	for _, ingressStatusIP := range coreDNSService.Status.LoadBalancer.Ingress {
		var confirmedIPs, err = extractIPFromLB(ingressStatusIP, r.config.ParentZoneDNSServers)
		if err != nil {
			return nil, nil, err
		}
		ipList = append(ipList, confirmedIPs...)
	}
	return ipList, coreDNSService, nil
}
